package com.Arsanesia.TempleRush.Models;

import com.Arsanesia.TempleRush.Enumeration.BlockStateEnumeration;
import com.Arsanesia.TempleRush.Enumeration.GeenieEnumeration;
import com.Arsanesia.TempleRush.Enumeration.Notif;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Array;

public class Block implements Updateable{
	private final float BUILDANIMATION_TIME = 0.1f;
	private final float MASKANIMATION_TIME = BUILDANIMATION_TIME*3;
	private final float FIREANIMATION_TIME = 0.25f;
    public static final int TOP_FLOOR = 8;
    private final float POSITION_ADJUSTMENT = 1.5f;
	public static float WIDTH;
	public static float HEIGHT;
	
	private GeenieEnumeration color;
	private BlockStateEnumeration state;
	private int column;
	private int floor;
	private TextureRegion defaultregion;
	private TextureRegion blockTexture;
	private Animation fireAnimation;
	private Animation buildAnimation;
	private Animation maskAnimation;
	private Image blockImage;
	private Image blockAnimation;
	private Image blockMask;
	private float stateTime;
	private boolean flip;
	TextureRegion currentBlockFrame;
	TextureRegion currentAnimationFrame;
	TextureRegion currentMaskFrame;
	private float defaultX, defaultY;
	private float topFloorX;
	
	public Block(TextureRegion blankimage){
        //create blank images
		defaultregion = new TextureRegion(blankimage);
        blockImage = new Image(new TextureRegionDrawable(new TextureRegion(defaultregion)));
        blockAnimation = new Image(new TextureRegionDrawable(new TextureRegion(defaultregion)));
        blockMask = new Image(new TextureRegionDrawable(new TextureRegion(defaultregion)));
	}
	public void init(int floor, int column, TextureRegion temple, Array<Sprite> templeBuildAnimation, boolean flipping){
		//initiate temple block
		this.floor = floor;
        this.column = column;
        this.flip = flipping;
        stateTime = 0f;
        //copy the region
        blockTexture = new TextureRegion(temple);
        //flip the block if needed
        if(flip)blockTexture.flip(true, false);
        //get block size
        WIDTH = blockTexture.getRegionWidth()-POSITION_ADJUSTMENT;
        HEIGHT = blockTexture.getRegionHeight()-POSITION_ADJUSTMENT;
        //create the built animation
        buildAnimation = new Animation(BUILDANIMATION_TIME,templeBuildAnimation);
        
        defaultX = Temple.LEFT_MARGIN + (column - 1) * WIDTH;
        defaultY = Temple.BOTTOM_MARGIN +  floor * HEIGHT - HEIGHT + Temple.TEMPLE_HEIGHTADJUSTMENT;
        topFloorX = Temple.LEFT_MARGIN + 3 * WIDTH / 2;
 
        //set the image position	
        blockImage.setPosition(defaultX,defaultY );
        blockAnimation.setPosition(defaultX, defaultY);
        blockMask.setPosition(defaultX, defaultY);
        //set x image
        if(this.floor == TOP_FLOOR){
        	 blockImage.setX(topFloorX);
             blockAnimation.setX(topFloorX);
             blockMask.setX(topFloorX);
        }

	}
	
	public void addBlockToStage(Stage stage){
		 //add images to stage
        stage.addActor(blockImage);
        stage.addActor(blockAnimation);
        stage.addActor(blockMask);
	}
	//setter
	public void setState(BlockStateEnumeration _state) {
		this.state = _state;
		this.stateTime = 0f;
	}
	public void setAttributes(int color, BlockStateEnumeration state, Array<Sprite> fireSprites, Sprite maskSprite) {
		//set the animations 
		fireAnimation = new Animation(FIREANIMATION_TIME,fireSprites);
		maskAnimation = new Animation(MASKANIMATION_TIME,maskSprite);
		//set the block color
		this.color = GeenieEnumeration.values()[color];
		Gdx.app.log("colorNumber", "the color: "+this.color.name()+","+color);
		//set the state 
		this.state = state;
//		if(floor == TOP_FLOOR){
//			//use blockImage to draw the fire also
//			blockImage.setPosition(Temple.LEFT_MARGIN + 3 * WIDTH / 2, 120 + floor * HEIGHT);
//			blockMask.setPosition(Temple.LEFT_MARGIN + 3 * WIDTH / 2, 184 + floor * HEIGHT);
//		}else{
//			blockImage.setPosition(Temple.LEFT_MARGIN + (column - 1) * WIDTH / 2, 120 + floor * HEIGHT);
//			blockMask.setPosition(Temple.LEFT_MARGIN + (column - 1) * WIDTH / 2, 184 + floor * HEIGHT);
//		}
	}
	//getter
	public int getColor() {
		return this.color.ordinal();
	}

	public BlockStateEnumeration getBlockState(){
		return state;
	}
	public boolean isBuilt() {
	    return state == BlockStateEnumeration.BUILDED;
	}
	
    public boolean needUpdate() {
        return state != BlockStateEnumeration.BUILDED;
    }
	
    public boolean needRender() {
        return state != BlockStateEnumeration.NON_ACCESS;
    }
    
    public Notif checkTouch(float x,float y, GeenieEnumeration color) {
        float blockBorder = Temple.LEFT_MARGIN + (column - 1) * WIDTH;
        float rightBorder = blockBorder+WIDTH;
        
        /*
         * Floor 8 is special case, beacuse only one fire is used for finishing
         * two blocks
         */
        if (floor == 8) {
            blockBorder = Temple.LEFT_MARGIN + 3 * WIDTH / 2;
        }

        float distanceLeft = Math.abs(blockBorder - x);
        float distanceRight = Math.abs(rightBorder - x);
        if (state == BlockStateEnumeration.READY
                && (distanceLeft < Temple.TOLERANCE_DISTANCE||distanceRight<rightBorder+Temple.TOLERANCE_DISTANCE)
                && color == this.color) {
            setState(BlockStateEnumeration.ANIMATE);
//            animTime = nowTime;
//
            //set block image to be fallen from abo
            blockImage.setY(y);
            blockImage.addAction(Actions.moveTo(blockImage.getX(), defaultY,MASKANIMATION_TIME));
            if ((x< blockBorder && distanceLeft >3)|| (x>rightBorder && distanceRight>3)) {
                return Notif.GREAT;
            } else {
                return Notif.PERFECT;
            }

        } else {
            return Notif.MISS;
        }
    }
    @Override
    public void update(){
    	//get the animation time
		stateTime+= Gdx.graphics.getDeltaTime();
		//create empty texture region
		currentBlockFrame =  new TextureRegion(defaultregion);
		currentAnimationFrame = new TextureRegion(defaultregion);
		currentMaskFrame = new TextureRegion(defaultregion);
		
    	if(state == BlockStateEnumeration.READY){
    		currentBlockFrame = new TextureRegion(fireAnimation.getKeyFrame(stateTime,true));
    	}else if(state == BlockStateEnumeration.ANIMATE){
    		boolean maskfinish = false, buildfinish = false;
    		currentBlockFrame = new TextureRegion(blockTexture);
    		//currentBlockFrame = new TextureRegion(blockTexture);
    		Gdx.app.log("animating_temple", "animated");
    		currentMaskFrame = new TextureRegion(maskAnimation.getKeyFrame(stateTime,false));
    		currentAnimationFrame = new TextureRegion(buildAnimation.getKeyFrame(stateTime,false));
    		if(maskAnimation.isAnimationFinished(stateTime)){
    			currentMaskFrame = new TextureRegion(defaultregion);
    			maskfinish = true;
    		}
    		if(buildAnimation.isAnimationFinished(stateTime)){
    			currentAnimationFrame = new TextureRegion(defaultregion);
    			buildfinish = true;
    		}
    		if(maskfinish && buildfinish) {
    			
    			setState(BlockStateEnumeration.BUILDED);
    			//reset the block image position to default
    			if(this.floor == TOP_FLOOR){
		        	 blockImage.setX(defaultX);
		        }
    			Gdx.app.log("temple instance", "block builded");
    		}
    	}else if(state == BlockStateEnumeration.BUILDED){
    		Gdx.app.log("temple instance", "block finished");
    	}
    	

    	//add texture region to image
    	blockImage.setDrawable(new TextureRegionDrawable(currentBlockFrame));
    	blockAnimation.setDrawable(new TextureRegionDrawable(currentAnimationFrame));
    	blockMask.setDrawable(new TextureRegionDrawable(currentMaskFrame));
    	    	
    }
    

}
